<template>
  <div class="mindmap-container">
    <div class="toolbar">
      <Button type="primary" @click="addRootNode" icon="md-add">添加根节点</Button>
      <Button @click="resetCanvas" icon="md-refresh" style="margin-left: 10px;">重置画布</Button>
      <Button @click="saveNodeFromButton()" icon="md-refresh" style="margin-left: 10px;">保存节点</Button>
    </div>

    <!-- 网格背景 (独立于画布) -->
    <div class="grid-background" :style="{ transform: `scale(${scale})` }"></div>

    <!-- 脑图画布 -->
    <div class="mindmap-canvas" ref="mindmapCanvas"
         @mousedown="startCanvasDrag"
         :style="{ transform: `translate(${canvasOffsetX}px, ${canvasOffsetY}px) scale(${scale})` }">

      <!-- 连接线 -->
      <svg class="connections-svg" width="100%" height="100%">
        <defs>
          <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
            <polygon points="0 0, 10 3.5, 0 7" fill="#2d8cf0" />
          </marker>
        </defs>

        <!-- 现有连接线 -->
        <g v-for="connection in connections" :key="connection.id">
          <path
            :d="getBezierPath(connection)"
            stroke="#2d8cf0"
            stroke-width="2"
            stroke-dasharray="5,5"
            fill="none"
            marker-end="url(#arrowhead)"
            class="connection-path"
            @mousedown.stop="startDragConnection($event, connection)"
            @contextmenu.stop="openConnectionMenu($event, connection)"
          />
          <!-- 连接线文字 -->
          <text
            :x="(connection.startX + connection.endX) / 2"
            :y="(connection.startY + connection.endY) / 2 - 10"
            font-size="12"
            fill="#666"
            text-anchor="middle"
            dominant-baseline="middle"
            @dblclick.stop="editConnectionText(connection)"
            style="cursor: pointer;"
          >{{ connection.text }}</text>
        </g>

        <!-- 正在绘制的连接线 -->
        <g v-if="isConnecting && tempConnection">
          <path
            :d="`M ${tempConnection.startX} ${tempConnection.startY} L ${tempConnection.endX} ${tempConnection.endY}`"
            stroke="#19be6b"
            stroke-width="2"
            stroke-dasharray="5,5"
            fill="none"
            marker-end="url(#arrowhead)"
            class="connection-path-draft"
          />
        </g>
      </svg>

      <!-- 脑图节点 -->
      <div
        v-for="node in mindmapNodes"
        :key="node.id"
        class="mindmap-node"
        :class="{ 'selected': selectedNode?.id === node.id }"
        :style="{ left: node.x + 'px', top: node.y + 'px' }"
        @click="selectNode(node)"
        @mousedown="startDrag($event, node)"
        @dblclick="editNode(node)"
      >
        <!-- 输入连接点 -->
        <div class="handle handle-left" @mousedown.stop="startConnection($event, node, 'input')"></div>

        <!-- 节点内容 -->
        <div class="node-content">
            <div class="node-title">{{ node.name }}</div>
            <div v-if="node.remark" class="node-remark">{{ node.remark }}</div>
          </div>

        <!-- 节点操作按钮 -->
        <div class="node-actions">
          <Icon type="md-add" @click.stop="addChildNode(node)" class="action-btn add" title="添加子节点" />
          <Icon type="md-trash" @click.stop="deleteNode(node)" class="action-btn delete" title="删除节点" />
        </div>

        <!-- 输出连接点 -->
        <div class="handle handle-right" @mousedown.stop="startConnection($event, node, 'output')"></div>
      </div>
    </div>

    <!-- 新增/编辑节点弹窗 -->
  <Modal
    v-model="showNodeModal"
    :title="modalTitle"
    width="400"
    @on-ok="saveNode"
    @on-cancel="cancelEdit"
  >
    <Form ref="nodeForm" :model="nodeForm" :rules="nodeRules" :label-width="80" @submit.native.prevent>
      <FormItem label="节点名称" prop="name">
        <Input v-model="nodeForm.name" placeholder="请输入节点名称" @keyup.enter.native="saveNode" />
      </FormItem>
      <FormItem label="节点备注" prop="remark">
        <Input v-model="nodeForm.remark" placeholder="请输入节点备注（选填）" type="textarea" rows="3" />
      </FormItem>
    </Form>
  </Modal>

  <!-- 编辑连接文字弹窗 -->
  <Modal
    v-model="showConnectionTextModal"
    title="编辑连接文字"
    width="400"
    @on-ok="saveConnectionText"
    @on-cancel="showConnectionTextModal = false"
  >
    <Form ref="connectionTextForm" :model="connectionTextForm" :label-width="80" @submit.native.prevent>
      <FormItem label="连接文字" prop="text">
        <Input v-model="connectionTextForm.text" placeholder="请输入连接文字" @keyup.enter.native="saveConnectionText" />
      </FormItem>
    </Form>
  </Modal>

  <!-- 连接上下文菜单 -->
  <div ref="connectionMenu" class="connection-menu"
    @click.stop
    @mouseleave="closeConnectionMenu"
  >
    <div class="menu-item" @click.stop="editConnectionText(selectedConnection)">编辑文字</div>
    <div class="menu-item" @click.stop="deleteConnection(selectedConnection)">删除连接</div>
  </div>
  </div>
  </template>

<style scoped>
  .connection-menu {
    position: absolute;
    background: white;
    border: 1px solid #ddd;
    border-radius: 4px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    padding: 6px 0;
    z-index: 1000;
    display: none;
    min-width: 100px;
  }

  .menu-item {
    padding: 6px 12px;
    cursor: pointer;
    font-size: 12px;
  }

  .menu-item:hover {
    background-color: #f5f5f5;
  }
</style>

<script>
import { Message, Modal } from 'iview';

export default {
  name: 'Mindmap',
  data() {
    return {
      selectedNode: null,
      selectedConnection: null,
      showNodeModal: false,
      showConnectionTextModal: false,
      modalTitle: '新增节点',
      isEditing: false,
      editingNodeId: null,
      draggingNode: null,
      connectingNode: null,
      connectionType: null,
      isConnecting: false,
      tempConnection: null,
      draggingConnection: null,
      dragStartX: 0,
      dragStartY: 0,
      dragControlPoint: null,
      scale: 1, // 固定缩放比例为1

      canvasDragging: false,
      canvasStartX: 0,
      canvasStartY: 0,
      canvasOffsetX: 0,
      canvasOffsetY: 0,

      connectionTextForm: { text: '' },

      // 节点表单
      nodeForm: {
        name: '',
        x: 100,
        y: 100,
        remark: ''
      },

      // 表单验证规则
      nodeRules: {
        name: [
            { required: true, message: '请输入节点名称', trigger: 'blur' }
          ],
          remark: []
      },

      // 脑图节点数据
      mindmapNodes: [
        {
          id: 1,
          name: '根节点',
          x: 400,
          y: 200,
          remark: '这是一个根节点示例'
        }
      ],

      // 连接线数据
      connections: []
    };
  },
  mounted() {
    this.bindEvents();
  },
  beforeDestroy() {
    document.removeEventListener('mousemove', this.onMouseMove);
    document.removeEventListener('mouseup', this.onMouseUp);
  },
  methods: {
    // 绑定事件
    bindEvents() {
      document.addEventListener('mousemove', this.onMouseMove);
      document.addEventListener('mouseup', this.onMouseUp);
    },

    // 选择节点
    selectNode(node) {
      this.selectedNode = node;
    },

    // 编辑节点
    editNode(node) {
      this.isEditing = true;
      this.editingNodeId = node.id;
      this.modalTitle = '编辑节点';
      this.nodeForm = {...node};
      this.showNodeModal = true;
    },

    // 添加根节点
    addRootNode() {
      this.isEditing = false;
      this.editingNodeId = null;
      this.modalTitle = '添加根节点';
      this.nodeForm = {
        name: '',
        x: 400 * this.scale,
        y: 200 * this.scale
      };
      this.showNodeModal = true;
    },

    // 添加子节点
    addChildNode(parentNode) {
      this.isEditing = false;
      this.editingNodeId = null;
      this.modalTitle = '添加子节点';

      // 计算子节点位置
      const childCount = this.mindmapNodes.filter(n =>
        this.connections.some(c => c.fromNode === parentNode.id && c.toNode === n.id)
      ).length;

      const angle = (childCount * 60) * (Math.PI / 180);
      const distance = 150 * this.scale;
      const x = parentNode.x + Math.cos(angle) * distance;
      const y = parentNode.y + Math.sin(angle) * distance;

      this.nodeForm = {
        name: '',
        x: Math.round(x),
        y: Math.round(y)
      };
      this.showNodeModal = true;
    },

    // 保存节点
    saveNode() {
      this.$refs.nodeForm.validate((valid) => {
        if (valid) {
          if (this.isEditing) {
            // 编辑节点
            const index = this.mindmapNodes.findIndex(n => n.id === this.editingNodeId);
            if (index !== -1) {
              this.mindmapNodes[index] = { ...this.nodeForm };
            }
            Message.success('节点编辑成功');
          } else {
            // 新增节点
            const newNode = {
              ...this.nodeForm,
              id: Date.now()
            };
            this.mindmapNodes.push(newNode);
            Message.success('节点添加成功');
          }

          this.showNodeModal = false;
          this.selectedNode = null; // 清空选中状态
        }
      });
    },

    // 取消编辑
    cancelEdit() {
      this.showNodeModal = false;
      this.selectedNode = null;
    },

    // 从按钮保存节点
    saveNodeFromButton() {
      console.info('保存节点:', this.mindmapNodes);
      Message.success('节点信息已打印到控制台');
    },

    // 重置画布位置
    resetCanvas() {
      this.canvasOffsetX = 0;
      this.canvasOffsetY = 0;

      // 更新连接线
      this.updateConnections();
      Message.success('画布已重置');
    },

    // 开始拖拽节点
    startDrag(event, node) {
      this.draggingNode = node;
      event.preventDefault();
    },

    // 开始连接
    startConnection(event, node, type) {
      this.isConnecting = true;
      this.connectingNode = node;
      this.connectionType = type;

      // 计算起始点坐标
      const rect = this.$refs.mindmapCanvas.getBoundingClientRect();
      const startX = node.x + (type === 'output' ? 100 : 0);
      const startY = node.y + 25;

      this.tempConnection = {
        startX: startX,
        startY: startY,
        endX: event.clientX - rect.left - this.canvasOffsetX,
        endY: event.clientY - rect.top - this.canvasOffsetY
      };

      event.preventDefault();
    },

    // 计算折线路径
    getBezierPath(connection) {
      // 对于折线，我们使用L命令连接各个点
      if (connection.midPoints && connection.midPoints.length > 0) {
        let path = `M ${connection.startX} ${connection.startY}`;
        connection.midPoints.forEach(point => {
          path += ` L ${point.x} ${point.y}`;
        });
        path += ` L ${connection.endX} ${connection.endY}`;
        return path;
      } else {
        // 如果没有中间点，使用直线
        return `M ${connection.startX} ${connection.startY} L ${connection.endX} ${connection.endY}`;
      }
    },

    // 更新连接线
    updateConnections() {
      this.connections = this.connections.map(connection => {
        const fromNode = this.mindmapNodes.find(n => n.id === connection.fromNode);
        const toNode = this.mindmapNodes.find(n => n.id === connection.toNode);

        if (fromNode && toNode) {
          // 精确计算连接点位置
          const startX = fromNode.x + 100;  // 右连接点（节点宽度为100px）
          const startY = fromNode.y + 25;   // 垂直居中（节点高度为50px）
          const endX = toNode.x;            // 左连接点
          const endY = toNode.y + 25;       // 垂直居中

          // 计算水平和垂直距离
          const dx = endX - startX;
          const dy = endY - startY;

          // 确定转折点 - 优先水平方向转折
          let midPoints = [];
          if (Math.abs(dy) > Math.abs(dx)) {
            // 垂直方向转折
            const midY = startY + dy / 2;
            midPoints = [
              { x: startX, y: midY },
              { x: endX, y: midY }
            ];
          } else {
            // 水平方向转折
            const midX = startX + dx / 2;
            midPoints = [
              { x: midX, y: startY },
              { x: midX, y: endY }
            ];
          }

          return {
            ...connection,
            startX,
            startY,
            endX,
            endY,
            midPoints
          };
        }
        return connection;
      });
      // 强制更新视图
      this.$forceUpdate();
    },

    // 开始拖拽连接线
    startDragConnection(event, connection) {
      this.draggingConnection = connection;
      this.dragStartX = event.clientX;
      this.dragStartY = event.clientY;

      // 简单判断点击位置接近哪个点
      const rect = this.$refs.mindmapCanvas.getBoundingClientRect();
      const clickX = event.clientX - rect.left - this.canvasOffsetX;
      const clickY = event.clientY - rect.top - this.canvasOffsetY;

      // 检查是否点击了中间点
      let closestPointIndex = -1;
      let minDistance = 20; // 点击阈值

      if (connection.midPoints) {
        connection.midPoints.forEach((point, index) => {
          const distance = Math.hypot(clickX - point.x, clickY - point.y);
          if (distance < minDistance) {
            minDistance = distance;
            closestPointIndex = index;
          }
        });
      }

      this.dragControlPoint = closestPointIndex !== -1 ? `midPoint${closestPointIndex}` : null;
      event.preventDefault();
    },

    // 鼠标移动
    onMouseMove(event) {
      // 画布拖动
      if (this.canvasDragging) {
        this.canvasOffsetX = event.clientX - this.canvasStartX;
        this.canvasOffsetY = event.clientY - this.canvasStartY;
        return;
      }

      // 连接线拖动
      if (this.draggingConnection && this.dragControlPoint) {
        const rect = this.$refs.mindmapCanvas.getBoundingClientRect();
        // 计算相对于画布的鼠标位置，考虑画布偏移和缩放
        const currentX = (event.clientX - rect.left - this.canvasOffsetX) / this.scale;
        const currentY = (event.clientY - rect.top - this.canvasOffsetY) / this.scale;
        const startX = (this.dragStartX - rect.left - this.canvasOffsetX) / this.scale;
        const startY = (this.dragStartY - rect.top - this.canvasOffsetY) / this.scale;
        const dx = currentX - startX;
        const dy = currentY - startY;

        // 提取中间点索引
        const pointIndex = parseInt(this.dragControlPoint.replace('midPoint', ''));
        if (!isNaN(pointIndex) && this.draggingConnection.midPoints && this.draggingConnection.midPoints[pointIndex]) {
          this.draggingConnection.midPoints[pointIndex].x += dx;
          this.draggingConnection.midPoints[pointIndex].y += dy;
        }

        this.dragStartX = event.clientX;
        this.dragStartY = event.clientY;
        // 强制更新视图
        this.$forceUpdate();
        return;
      }

      // 节点拖动
      if (this.draggingNode) {
        const rect = this.$refs.mindmapCanvas.getBoundingClientRect();
        // 简化计算，让节点直接跟随鼠标
        let newX = event.clientX - rect.left - 75; // 减去节点宽度的一半
        let newY = event.clientY - rect.top - 20;  // 减去节点高度的一半

        // 移除复杂的边界限制，允许节点自由移动
        // 仅保留基本的画布边界检查
        const canvasWidth = rect.width;
        const canvasHeight = rect.height;
        const nodeWidth = 150; // 节点宽度
        const nodeHeight = 40; // 节点高度

        // 简单限制节点不超出画布过多
        newX = Math.max(-nodeWidth, Math.min(newX, canvasWidth));
        newY = Math.max(-nodeHeight, Math.min(newY, canvasHeight));

        // 不再考虑缩放和画布偏移，直接设置节点位置
        this.draggingNode.x = newX;
        this.draggingNode.y = newY;
        this.updateConnections();
        // 强制更新视图
        this.$forceUpdate();
        return;
      }

        // 已在前面直接设置节点位置并更新视图
        // 此处不再重复执行

        // 更新临时连接线
      if (this.isConnecting && this.tempConnection) {
        const rect = this.$refs.mindmapCanvas.getBoundingClientRect();
        // 计算相对于画布的鼠标位置，考虑画布偏移和缩放
        this.tempConnection.endX = (event.clientX - rect.left - this.canvasOffsetX) / this.scale;
        this.tempConnection.endY = (event.clientY - rect.top - this.canvasOffsetY) / this.scale;
        // 强制更新视图
        this.$forceUpdate();
      }
    },

    // 鼠标释放
    onMouseUp(event) {
      if (this.isConnecting) {
        // 尝试完成连接
        const rect = this.$refs.mindmapCanvas.getBoundingClientRect();
        const mouseX = event.clientX - rect.left - this.canvasOffsetX;
        const mouseY = event.clientY - rect.top - this.canvasOffsetY;

        // 查找目标节点
        const targetNode = this.mindmapNodes.find(node => {
          const nodeX = node.x;
          const nodeY = node.y;
          return mouseX >= nodeX - 10 && mouseX <= nodeX + 110 &&
                 mouseY >= nodeY - 10 && mouseY <= nodeY + 60;
        });

        if (targetNode && targetNode.id !== this.connectingNode.id) {
            // 创建新连接
            const startX = this.connectionType === 'output' ? this.connectingNode.x + 100 : targetNode.x + 100;
            const startY = this.connectionType === 'output' ? this.connectingNode.y + 25 : targetNode.y + 25;
            const endX = this.connectionType === 'output' ? targetNode.x : this.connectingNode.x;
            const endY = this.connectionType === 'output' ? targetNode.y + 25 : this.connectingNode.y + 25;

            const newConnection = {
              id: Date.now(),
              fromNode: this.connectionType === 'output' ? this.connectingNode.id : targetNode.id,
              toNode: this.connectionType === 'output' ? targetNode.id : this.connectingNode.id,
              startX: startX,
              startY: startY,
              endX: endX,
              endY: endY,
              midPoints: [],
              text: '连接线'
            };
            this.connections.push(newConnection);
            // 创建连接后更新连接线以添加转折点
            this.updateConnections();
            // 强制更新视图，确保连接创建后立即显示
            this.$forceUpdate();
            Message.success('连接创建成功');
          }
      }

      this.draggingNode = null;
      this.connectingNode = null;
      this.connectionType = null;
      this.isConnecting = false;
      this.tempConnection = null;
      this.draggingConnection = null;
      this.dragControlPoint = null;
      this.canvasDragging = false;
    },

    // 打开连接操作菜单
    openConnectionMenu(event, connection) {
      event.preventDefault();
      this.selectedConnection = connection;
      // 显示菜单并定位
      const menu = this.$refs.connectionMenu;
      menu.style.left = event.clientX + 'px';
      menu.style.top = event.clientY + 'px';
      menu.style.display = 'block';
    },

    // 关闭连接菜单
    closeConnectionMenu() {
      const menu = this.$refs.connectionMenu;
      menu.style.display = 'none';
    },

    // 删除连接
    deleteConnection(connection) {
      const index = this.connections.findIndex(c => c.id === connection.id);
      if (index !== -1) {
        this.connections.splice(index, 1);
        Message.success('连接已删除');
      }
      this.closeConnectionMenu();
    },

    // 编辑连接文字
    editConnectionText(connection) {
      this.selectedConnection = connection;
      this.connectionTextForm = { text: connection.text };
      this.showConnectionTextModal = true;
      this.closeConnectionMenu();
    },

    // 保存连接文字
    saveConnectionText() {
      if (this.selectedConnection) {
        const index = this.connections.findIndex(c => c.id === this.selectedConnection.id);
        if (index !== -1) {
          this.connections[index].text = this.connectionTextForm.text;
          Message.success('连接文字已更新');
        }
      }
      this.showConnectionTextModal = false;
    },

    // 删除节点
    deleteNode(node) {
      // 先删除相关连接
      this.connections = this.connections.filter(connection => {
        return connection.fromNode !== node.id && connection.toNode !== node.id;
      });

      // 再删除节点
      const index = this.mindmapNodes.findIndex(n => n.id === node.id);
      if (index !== -1) {
        this.mindmapNodes.splice(index, 1);
        this.selectedNode = null;
        Message.success('节点已删除');
      }
    },

    // 开始画布拖动
    startCanvasDrag(event) {
      // 如果点击的是节点或连接点，不启动画布拖动
      if (event.target.closest('.mindmap-node') || event.target.closest('.handle') || event.target.closest('.connection-path')) {
        return;
      }

      this.canvasDragging = true;
      this.canvasStartX = event.clientX - this.canvasOffsetX;
      this.canvasStartY = event.clientY - this.canvasOffsetY;
      event.preventDefault();
    },

    // 计算直接路径
    getBezierPath(connection) {
      // 直接连接起点和终点
      return `M ${connection.startX} ${connection.startY} L ${connection.endX} ${connection.endY}`;
    },

    // 更新连接线
    updateConnections() {
      this.connections = this.connections.map(connection => {
        const fromNode = this.mindmapNodes.find(n => n.id === connection.fromNode);
        const toNode = this.mindmapNodes.find(n => n.id === connection.toNode);

        if (fromNode && toNode) {
          const startX = fromNode.x + 100;
          const startY = fromNode.y + 25;
          const endX = toNode.x;
          const endY = toNode.y + 25;

          return {
            ...connection,
            startX,
            startY,
            endX,
            endY,
            // 删除中间点和控制点
            midPoints: [],
            controlPoint1X: undefined,
            controlPoint1Y: undefined,
            controlPoint2X: undefined,
            controlPoint2Y: undefined
          };
        }
        return connection;
      });
      // 强制更新视图
      this.$forceUpdate();
    }

  }
};
</script>

<style scoped>
.mindmap-container {
  padding: 20px;
  background: #f5f5f5;
  min-height: 600px;
  position: relative;
}

.toolbar {
  margin-bottom: 20px;
  padding: 10px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.mindmap-canvas {
  position: relative;
  background: transparent;
  border-radius: 8px;
  padding: 30px;
  min-height: 800px;
  width: 100%;
  overflow: visible;
  cursor: grab;
  transition: transform 0.2s;
  z-index: 1;
}

.mindmap-canvas:active {
  cursor: grabbing;
}

/* 网格背景 */
.grid-background {
  position: absolute;
  top: 90px; /* 工具栏高度约50px + margin-bottom:20px + 额外间距20px */
  left: 0;
  width: 200%;
  height: 200%;
  background-image:
    linear-gradient(rgba(0, 0, 0, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(0, 0, 0, 0.05) 1px, transparent 1px);
  background-size: 20px 20px;
  pointer-events: none;
  z-index: 0;
  transform-origin: top left;
}

/* 脑图节点样式 */
.mindmap-node {
  position: absolute;
  width: 150px;
  min-height: 40px;
  background: white;
  border: 2px solid #e8e8e8;
  border-radius: 10px;
  padding: 10px;
  cursor: pointer;
  transition: all 0.3s ease;
  z-index: 10;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  display: flex;
  align-items: center;
  justify-content: center;
}

.mindmap-node:hover {
  border-color: #2d8cf0;
  box-shadow: 0 4px 12px rgba(45, 140, 240, 0.2);
}

.mindmap-node.selected {
  border-color: #2d8cf0;
  background: #f0f8ff;
}

.node-content {
  text-align: center;
  width: 100%;
}

.node-title {
  font-weight: bold;
  font-size: 14px;
  color: #333;
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.node-remark {
  font-size: 12px;
  color: #666;
  line-height: 1.4;
  margin-top: 4px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}

.node-actions {
  position: absolute;
  top: 3px;
  right: 3px;
  display: flex;
  gap: 2px;
  opacity: 0;
  transition: opacity 0.3s;
}

.mindmap-node:hover .node-actions {
  opacity: 1;
}

.action-btn {
  color: #999;
  cursor: pointer;
  transition: color 0.3s;
  font-size: 12px;
  padding: 2px;
  border-radius: 3px;
}

.action-btn:hover {
  color: #19be6b;
}

/* 连接点 */
.handle {
  position: absolute;
  width: 10px;
  height: 10px;
  background: #2d8cf0;
  border: 2px solid white;
  border-radius: 50%;
  cursor: crosshair;
  transition: all 0.3s;
  z-index: 20;
}

.handle:hover {
  background: #19be6b;
  transform: scale(1.3);
  box-shadow: 0 0 8px rgba(25, 190, 107, 0.6);
}

.handle-left {
  left: -5px;
  top: 50%;
  transform: translateY(-50%);
}

.handle-right {
  right: -5px;
  top: 50%;
  transform: translateY(-50%);
}

/* 连接线样式 */
.connections-svg {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: all;
  z-index: 1;
}

.connection-path {
  transition: all 0.3s ease;
  cursor: move;
}

.connection-path:hover {
  stroke-width: 3;
}

.connection-path-draft {
  animation: dash 1s linear infinite;
}

@keyframes dash {
  to {
    stroke-dashoffset: -10;
  }
}

.connection-path-draft {
  stroke-dasharray: 5,5;
}
</style>


.action-btn.delete:hover {
  color: #ff4949;
}